﻿// Copyright (C) 2012 Kim Jensen, TaskJunction.com
// Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Json;
using TaskJunctionLib.Model;

namespace TaskJunctionLib.Mapping.JSON
{
    public abstract class JSONMapper<T> : IObjectMapper<T> where T : ModelEntity, new()
    {
        public string serialize(T obj) {
           return serializeToJSONObject(obj).ToString(JsonSaveOptions.None);
        }

        public string serializeList(IList<T> list)
        {
            return new JsonArray(list.Select(x => serializeToJSONObject(x))).ToString(JsonSaveOptions.None);
        }

        public T deserialize(string data)
        {
            var obj = new T();
            deserialize(data, obj);
            return obj;
        }

        public void deserialize(string data, T obj)
        {
            var resName = JSONName();
            var jwrap = JsonValue.Parse(data);
            if (jwrap.ContainsKey(resName))
            {
                var j = jwrap[resName];
                deserializeFromJSON(j, obj);
            }
        }

        public IList<T> deserializeList(string data)
        {
            var j = JsonValue.Parse(data);
            var list = createList(j);
            var resName = JSONName();
            for (int i = (list is PagedList<T>) ? 1 : 0; i < j.Count; i++)
            {
                list.Add(deserializeFromJSON(j[i][resName]));
            }
            return list;
        }

        private IList<T> createList(JsonValue j)
        {
            if (j.Count > 0)
            {
                var job = j[0];
                if (job.ContainsKey("pageinfo"))
                {
                    var pageinfo = job["pageinfo"];
                    return new PagedList<T>(pageinfo["page"].ReadAs<int>(1), pageinfo["total_pages"].ReadAs<int>(1));
                }
            }
            return new List<T>();
        }

        protected JsonObject serializeToJSONObject(T obj)
        {
            var j = new JsonObject();
            serializeToJSON(j, obj);

            var jwrap = new JsonObject();
            jwrap.Add(JSONName(), j);

            return jwrap;
        }

        public T deserializeFromJSON(JsonValue jsonObject)
        {
            var obj = new T();
            deserializeFromJSON(jsonObject, obj);
            return obj;
        }

        public abstract void deserializeFromJSON(JsonValue jsonObject, T obj);

        public abstract void serializeToJSON(JsonValue jsonObject, T obj);

        protected abstract string JSONName();
    }
}
